package kr.co.redcircle.net.multicast;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.net.UnknownHostException;

import kr.co.redcircle.net.multicast.handler.COMM00ResponseHandler;
import kr.co.redcircle.net.multicast.handler.COMM01ResponseHandler;
import kr.co.redcircle.net.multicast.handler.COMM02ResponseHandler;
import kr.co.redcircle.net.multicast.handler.COMM03ResponseHandler;
import net.sf.json.JSONObject;

public class MulticastNetworkService {

	private static String serviceHost;
	private static int servicePort;
	private static InetAddress grp;
	private static MulticastSocket s;
	private static int receveBufferLength;
	private static byte eofByte = 0x7F;
	private static String eofString = new String(new byte[]{eofByte});
	private static String zeroString = new String(new byte[]{0x00});
	private static MulticastResponseCollection respCollection = null;


	public static void init(String host, int port, int recvBufferLength) {
		serviceHost = host;
		servicePort = port;
		receveBufferLength = recvBufferLength;
		setResponseHandlerCollection();
	    try {
			grp = InetAddress.getByName(serviceHost);
			s = new MulticastSocket(port);
			s.setTimeToLive(32);
			s.joinGroup(grp);
		} catch (UnknownHostException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}

	}

	public static void send(MulticastRequest request) {
		try {		
			String msg = request.toString() + eofString;
			msg = URLEncoder.encode(msg, "UTF-8");
			
			System.out.println("send : " + msg);
		    DatagramPacket hi = new DatagramPacket(msg.getBytes(), msg.length(), grp, servicePort);
			s.send(hi);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private static boolean recv() {
	    DatagramPacket recv = new DatagramPacket(new byte[receveBufferLength], receveBufferLength);
	    //synchronized (recv) {
		    try {
				s.receive(recv);
				String recvOrgString = new String(recv.getData());
		        String decodeString = URLDecoder.decode (recvOrgString, "UTF-8");
		        String targetString = decodeString.replaceAll(zeroString , "");
		        targetString = targetString.replaceAll(eofString, "");
		        JSONObject jsonObj = JSONObject.fromObject(targetString);
		        String mode = (String) jsonObj.get("mode");
		        
		        if (mode.equals("EXIT")){
		        	close();
		        	return true;
		        }else{
			        respCollection.get(mode).invoke(jsonObj);
		        }
			} catch (IOException e) {
				e.printStackTrace();
			}
	    //}
		return false;
	}

	public static void close() {
		try {
			System.out.println("leaveGroup~! for close()");
			s.leaveGroup(grp);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private static void setResponseHandlerCollection() {
		// make handler with xml
		MulticastResponseCollection responseCollection = new MulticastResponseCollection();
		responseCollection.put("COMM00", new COMM00ResponseHandler());
		responseCollection.put("COMM01", new COMM01ResponseHandler());
		responseCollection.put("COMM02", new COMM02ResponseHandler());
		responseCollection.put("COMM03", new COMM03ResponseHandler());

		respCollection = responseCollection;
	}

	public static void startListener() {
		new Thread(new Runnable(){

			@Override
			public void run() {
				while(true) {
					if (recv()){
						break;
					}
				}
			}
		}).start();
	}

}
